<?php

include("core/controller.php");
include("core/versionHandler.php");
include("models/manager/tableInfos.php");
/**
 * This Controller is used to install a version
 * @copyright inovia
 * @package oolime_manager
 *
 */
class Scaffolding extends Controller {
	 
	 
	//todo verifier le niveau d'utilisateur
	protected function isLegitimate(){
		/**
		 * Tests the request parameter
		 */
		$ok=true;

		// are there empty fields ?
		$tabVerify = Array(
			"scaff_table"  => Array("string","Invalid Table name"),
			"scaff_generic" => Array("string","Generic name is empty"),
		);
		// are the directories ok ?
		if($this->request->get('scaff_modelDir') != '')
		$tabVerify["scaff_modelDir"] = Array("string","Invalid model directory name");
		if($this->request->get('scaff_controlerDir') != '')
		$tabVerify["scaff_controlerDir"] = Array("string","Invalid controller directory name");
		if($this->request->get('scaff_viewDir') != '')
		$tabVerify["scaff_viewDir"] = Array("string","Invalid view directory name");

		if(!$this->request->check($tabVerify)){
			$ok=false;
		}else{
			// table name is safe
			// check if the given Table exists in DB
			$check = new TableInfos();
			if(!$check->tableExists($this->request->get('scaff_table'))){
				$this->response->addError('Table "'.$this->request->get('scaff_table').'" does not exist','scaff_table');
				$ok=false;
			}
		}
		// is there an action selected ?
		if(!$this->request->get('scaff_get') && !$this->request->get('scaff_add')
		&& !$this->request->get('scaff_update') && !$this->request->get('scaff_delete')){
			$this->response->addError('No action selected','scaff_action');
			$ok=false;
		}
		// check if file names can be automatically generated
		if($this->request->get('scaff_generic') == $this->request->get('scaff_table') && $this->request->get('scaff_prefix') == ''){
			$this->response->addError('You should choose a prefix to avoid name collisions','scaff_prefix');
			$ok=false;
		}

		return $ok;
	}
	 
	 
	/**
	 * Function doing default actions of the Controller
	 *
	 */
	protected function defaultActions(){

		$obj->scaff_table        = $this->request->get('scaff_table');
		$obj->scaff_generic      = $this->request->get('scaff_generic');
		$obj->scaff_prefix       = $this->request->get('scaff_prefix');
		$obj->scaff_modelDir     = $this->request->get('scaff_modelDir');
		$obj->scaff_controlerDir = $this->request->get('scaff_controlerDir');
		$obj->scaff_controlerDir = $this->request->get('scaff_viewDir');
		$obj->scaff_get          = $this->request->get('scaff_get');
		$obj->scaff_add          = $this->request->get('scaff_add');
		$obj->scaff_addForm      = $this->request->get('scaff_addForm');
		$obj->scaff_update       = $this->request->get('scaff_update');
		$obj->scaff_updateForm   = $this->request->get('scaff_updateForm');
		$obj->scaff_delete       = $this->request->get('scaff_delete');

		$tab = Array(
     'scaff_table' => 'scaff_table',
     'scaff_generic' => 'scaff_generic',
     'scaff_prefix' => 'scaff_prefix',
     'scaff_modelDir' => 'scaff_modelDir',
     'scaff_controlerDir' => 'scaff_controlerDir',
     'scaff_viewDir' => 'scaff_viewDir',
     'scaff_get' => 'scaff_get',
     'scaff_add' => 'scaff_add',
     'scaff_addForm' => 'scaff_addForm',
     'scaff_update' => 'scaff_update',
     'scaff_updateForm' => 'scaff_updateForm',
     'scaff_delete' => 'scaff_delete'
     );

     $data = $this->response->mapObjectXML($obj, 'scaffolding', $tab);
     $this->response->add($data);

     $this->response->setXSLT("views/manager/scaffolding.xsl");
	}




	/**
	 * Function doing the actions of the Controller
	 *
	 */
	protected function actions(){
		$result = array();
		$dispatcherComment = '/** Add the following lines to the dipatcher to register controllers  **/';

		$dispatcher = array();
		$dispatcher = array();
		// tableName
		$tableName=$this->request->get('scaff_table');

		// mode
		if($this->request->get('scaff_overwrite')=='on')
		$mode='w';
		else
		$mode='x';

		// model path
		$modelPath='models/';
		if($this->request->get('scaff_modelDir') != '')
		$modelPath.=$this->request->get('scaff_modelDir').'/';

		// controlers path
		$controlsPath='controls/';
		if($this->request->get('scaff_controlerDir') != '')
		$controlsPath.=$this->request->get('scaff_controlerDir').'/';

		// views path
		$viewsPath='views/';
		if($this->request->get('scaff_viewDir') != '')
		$viewsPath.=$this->request->get('scaff_viewDir').'/';

		// prefix used
		if($this->request->get('scaff_prefix') != ''){
			$prefix=$this->request->get('scaff_prefix').'_';
		}else{
			$prefix='';
		}

		// MODEL file
		$modelName=$prefix.$tableName.'.php';
		$result[]=$this->generateModel($modelPath,$modelName,$mode,$tableName);

		// CONTROLLERS
		if($this->request->get('scaff_get')){
			// GET
			$genericName=$prefix.'get'.ucfirst($tableName);
			$result[]=$this->generateControllerGet($controlsPath,$genericName,$mode,$tableName,$prefix,$modelPath.$modelName);
			$dispatcher[]='"get'.ucfirst($tableName).'" => Array("'.$genericName.'", "'.$controlsPath.'"     , "xml",  true)';

		}
		if($this->request->get('scaff_add')){
			// ADD
			$genericName=$prefix.'add'.ucfirst($tableName);
			$view=$this->request->get('scaff_addForm');
			$result[]=$this->generateControllerAdd($controlsPath,$genericName,$mode,$tableName,$prefix,$modelPath.$modelName,$view,$viewsPath);

			if($view=='xsl') $ext='xsl';
			else $ext='xml';

			$dispatcher[]='"add'.ucfirst($tableName).'" => Array("'.$prefix.'add'.ucfirst($tableName).'", "'.$controlsPath.'"     , "'.$ext.'",  true)';
			if($view!='none'){
				$result[]=$this->generateView($viewsPath,$genericName,$view,$mode,$tableName,'add');
			}

		}
		if($this->request->get('scaff_update')){
			// UPDATE
			$genericName=$prefix.'update'.ucfirst($tableName);
			$view=$this->request->get('scaff_addForm');

			if($view=='xsl') $ext='xsl';
			else $ext='xml';

			$result[]=$this->generateControllerUpdate($controlsPath,$genericName,$mode,$tableName,$prefix,$modelPath.$modelName,$view,$viewsPath);
			$dispatcher[]='"update'.ucfirst($tableName).'" => Array("'.$prefix.'update'.ucfirst($tableName).'", "'.$controlsPath.'"     , "'.$ext.'",  true)';
			if($view!='none'){
				$result[]=$this->generateView($viewsPath,$genericName,$view,$mode,$tableName,'update');
			}

		}
		if($this->request->get('scaff_delete')){
			// DELETE
			$genericName=$prefix.'delete'.ucfirst($tableName);
			$result[]=$this->generateControllerDelete($controlsPath,$genericName,$mode,$tableName,$prefix,$modelPath.$modelName);
			$dispatcher[]='"delete'.ucfirst($tableName).'" => Array("'.$prefix.'delete'.ucfirst($tableName).'", "'.$controlsPath.'"    , "xml",  true)';

		}

		// write controlers in dispatcher
		//$conf=new ConfigFile('actions.php');


		// RESULT in xml
		$tab = Array('result'=>'result');
		foreach($result as $val){
			$obj->result = $val;
			$data = $this->response->mapObjectXML($obj, 'scaffInfo', $tab);
			$this->response->add($data);
		}
		if(count($dispatcher)>1){
			 
			$nodeEl = $this->response->doc->createElement('dispatcherComment');
			$nodeEl->appendChild($this->response->doc->createTextNode($dispatcherComment));
			$this->response->add($nodeEl);
			foreach($dispatcher as $val){
				$obj->result = $val;
				$data = $this->response->mapObjectXML($obj, 'scaffDispatcher', $tab);
				$this->response->add($data);
			}
		}
		$this->response->setXSLT("views/manager/scaffolding.xsl");
	}



	/*********/
	/* MODEL */
	/*********/

	/**
	 * Function generating a MODEL class template
	 *
	 */
	protected function generateModel($path,$name,$mode,$table){
		// open file
		if(!$file = @fopen($path.$name,$mode)){
			if($mode=='x')
			return 'ERROR : "'.$path.$name.'" already exists !';
			else
			return 'ERROR : "'.$path.$name.'" cannot be opened !';
		}

		// columns of the table
		$colsText='';
		$sep='';
		$check = new TableInfos();
		$cols=$check->tableRows($table);
		foreach($cols as $val){
			$colsText.=$sep.'      "'.$val[0].'" => "'.$val[0].'"';
			if($sep=='') $sep=",\n";
		}

		// content of the model
		$content= '<?php
include_once("core/mapped.php");
/**
 * Model class for table "'.$table.'"
 * Automatically generated
 *
 */
class '.ucfirst($table).' extends Mapped {
  public $table="'.$table.'";

  public function get'.ucfirst($table).'(){
    $tab=array(
'.$colsText.'
    );
    return $this->toXML(\''.$table.'\',$tab);
  }
}
?>';
		// write file
		if(@fwrite($file, $content) === FALSE) {
			return 'ERROR : "'.$path.$name.'" content not written';
		}
		return 'Model generated in '.$path.$name;
	}



	/*******/
	/* GET */
	/*******/

	/**
	 * Function generating the controller GET for a table
	 *
	 */
	protected function generateControllerGet($path,$name,$mode,$table,$prefix,$model){
		// open file
		if(!$file = @fopen($path.$name.'.php',$mode)){
			if($mode=='x')
			return 'ERROR : "'.$path.$name.'.php" already exists !';
			else
			return 'ERROR : "'.$path.$name.'.php" cannot be opened !';
		}
		// content of the controller
		$content= '<?php
include("core/controller.php");
include("'.$model.'");

/**
 * Get a row from the table '.$table.'
 *
 * @syntax : index.php?action=get'.ucfirst($table).'&id=xx
 * @version scaffolded
 */
class '.$prefix.'Get'.ucfirst($table).' extends Controller {

  function isLegitimate(){
    //request must contain an id
		$tabVerify = Array("id" => Array("int","An id is required"));
		return $this->request->check($tabVerify,4);
  }

  function actions(){
    $row=new '.ucfirst($table).'(\'r\',\'id\',$this->request->get(\'id\'));
    if(!$row->isOK()){
      $this->response->addError4("Id not found");
  	  return;
    }
    $nodes = $row->get'.ucfirst($table).'();
    $this->response->add($nodes);
  }

  function defaultActions(){}

}
?>';

		// write file
		if(@fwrite($file, $content) === FALSE) {
			return 'ERROR : "'.$path.$name.'.php" content not written';
		}

		return 'Controller "GET" generated in '.$path.$name.'.php';

	} /* END of GET controller */



	/*******/
	/* ADD */
	/*******/

	/**
	 * Function generating the controller ADD for a table
	 *
	 */
	protected function generateControllerAdd($path,$name,$mode,$table,$prefix,$model,$view,$viewPath){
		// open file
		if(!$file = @fopen($path.$name.'.php',$mode)){
			if($mode=='x')
			return 'ERROR : "'.$path.$name.'.php" already exists !';
			else
			return 'ERROR : "'.$path.$name.'.php" cannot be opened !';
		}

		// fields in databases
		$parameterTab='';
		$listFields='';
		$populateSeq='';
		$syntax='';
		$sep='';
		$check = new TableInfos();
		$cols=$check->tableRows($table);
		foreach($cols as $val){
			if($val[0] != 'id'){
				// check type
				$isNum=stristr($val[1],'int') || stristr($val[1],'dec') || stristr($val[1],'numeric')
				|| stristr($val[1],'float') || stristr($val[1],'real') || stristr($val[1],'double');
				if($isNum){
					$parameterTab.=$sep."\n".'      "'.$val[0].'" => Array("int","Wrong parameter")';
				}else{
					$parameterTab.=$sep."\n".'      "'.$val[0].'" => Array("string","Wrong parameter")';
				}

				// list of fields
				$listFields.=$sep.'"'.$val[0].'"';
				// populate row sequence
				$populateSeq.='    $row->field->'.$val[0].'=$this->request->get(\''.$val[0].'\');'."\n";
				// syntax
				$syntax.='&'.$val[0].'={'.$val[1].'}';
				if($sep=='') $sep=',';
			}
		}
		$setView='';
		if($view=='xsl'){
			$setView='$this->response->setXSLT("'.$viewPath.$prefix.'add'.ucfirst($table).'.xsl");';
		}

		// content of the controller
		$content= '<?php
include("core/controller.php");
include("'.$model.'");

/**
 * Add a row to the table '.$table.'
 *
 * @syntax : index.php?action=add'.ucfirst($table).$syntax.'
 * @version scaffolded
 */
class '.$prefix.'Add'.ucfirst($table).' extends Controller {

  function isLegitimate(){
    //check presence and type of parameters : TODO manually
    $tabVerify = Array('.$parameterTab.'
    );
		return $this->request->check($tabVerify,4);
  }

  function actions(){
    $row=new '.ucfirst($table).'(\'c\');

    // populate new row
    $row->range=array('.$listFields.');
'.$populateSeq.'
    $tab = Array("result"=>"result");
    $obj->result = "new entry added";
    $nodes = $this->response->mapObjectXML($obj, '.$table.', $tab);
    $this->response->add($nodes);
  }

  function defaultActions(){
    '.$setView.'
  }

}
?>';

		// write file
		if(@fwrite($file, $content) === FALSE) {
			return 'ERROR : "'.$path.$name.'.php" content not written';
		}

		return 'Controller "ADD" generated in '.$path.$name.'.php';

	} /* END of ADD controller */



	/**********/
	/* UPDATE */
	/**********/

	/**
	 * Function generating the controller UPDATE for a table
	 *
	 */
	protected function generateControllerUpdate($path,$name,$mode,$table,$prefix,$model,$view,$viewPath){
		// open file
		if(!$file = @fopen($path.$name.'.php',$mode)){
			if($mode=='x')
			return 'ERROR : "'.$path.$name.'.php" already exists !';
			else
			return 'ERROR : "'.$path.$name.'.php" cannot be opened !';
		}

		// fields in databases
		$parameterTab='';
		$listFields='';
		$populateSeq='';
		$syntax='';
		$sep='';
		$check = new TableInfos();
		$cols=$check->tableRows($table);
		foreach($cols as $val){
			if($val[0] != 'id'){
				// check type
				$isNum=stristr($val[1],'int') || stristr($val[1],'dec') || stristr($val[1],'numeric')
				|| stristr($val[1],'float') || stristr($val[1],'real') || stristr($val[1],'double');
				if($isNum){
					$parameterTab.=",\n".'      "'.$val[0].'" => Array("int","Wrong parameter")';
				}else{
					$parameterTab.=",\n".'      "'.$val[0].'" => Array("string","Wrong parameter")';
				}

				// list of fields
				$listFields.=$sep.'"'.$val[0].'"';
				// populate row sequence
				$populateSeq.='    if($this->request->get(\''.$val[0].'\')) $row->field->'.$val[0].'=$this->request->get(\''.$val[0].'\');'."\n";
				// syntax
				$syntax.='[&'.$val[0].'=...]';
				if($sep=='') $sep=',';
			}
		}
		$setView='';
		if($view=='xsl'){
			$setView='$this->response->setXSLT("'.$viewPath.$prefix.'update'.ucfirst($table).'.xsl");';
		}

		// content of the controller
		$content= '<?php
include("core/controller.php");
include("'.$model.'");

/**
 * Update a row of the table '.$table.'
 *
 * @syntax : index.php?action=update'.ucfirst($table).'&id=xx'.$syntax.'
 * @version scaffolded
 */
class '.$prefix.'Update'.ucfirst($table).' extends Controller {

  function isLegitimate(){
    //check presence and type of parameters : TODO manually
		$tabVerify = Array("id" => Array("int","An id is required")'.$parameterTab.');

		return $this->request->check($tabVerify,4);
  }

  function actions(){
    $row=new '.ucfirst($table).'(\'w\',\'id\',$this->request->get(\'id\'));

    // populate new row
    $row->range=array('.$listFields.');
'.$populateSeq.'
    $tab = Array("result"=>"result");
    $obj->result = "entry updated";
    $nodes = $this->response->mapObjectXML($obj, '.$table.', $tab);
    $this->response->add($nodes);
  }

  function defaultActions(){
    '.$setView.'
  }

}
?>';

		// write file
		if(@fwrite($file, $content) === FALSE) {
			return 'ERROR : "'.$path.$name.'.php" content not written';
		}

		return 'Controller "UPDATE" generated in '.$path.$name.'.php';

	} /* END of UPDATE controller */





	/**********/
	/* DELETE */
	/**********/

	/**
	 * Function generating the CONTROLLER DELETE for a table
	 *
	 */
	protected function generateControllerDelete($path,$name,$mode,$table,$prefix,$model){
		// open file
		if(!$file = @fopen($path.$name.'.php',$mode)){
			if($mode=='x')
			return 'ERROR : "'.$path.$name.'.php" already exists !';
			else
			return 'ERROR : "'.$path.$name.'.php" cannot be opened !';
		}

		// content of the controller
		$content= '<?php
include("core/controller.php");
include("'.$model.'");

/**
 * delete a row from table '.$table.'
 *
 * @syntax : index.php?action=delete'.ucfirst($table).'&id=xx
 * @version scaffolded
 */
class '.$prefix.'Delete'.ucfirst($table).' extends Controller {

  function isLegitimate(){
    //check presence and type of parameters
		$tabVerify = Array("id" => Array("int","An id is required"));
		return $this->request->check($tabVerify,4);
  }

  function actions(){
    $row=new '.ucfirst($table).'(\'w\',\'id\',$this->request->get(\'id\'));
    $row->delete();
  }

  function defaultActions(){}

}
?>';

		// write file
		if(@fwrite($file, $content) === FALSE) {
			return 'ERROR : "'.$path.$name.'.php" content not written';
		}

		return 'Controller "DELETE" generated in '.$path.$name.'.php';

	} /* END of DELETE controller */



	/********/
	/* VIEW */
	/********/
	protected function generateView($path,$actionName,$fileType,$mode,$table,$formType){
		$name=$actionName.'.'.$fileType;
		// open file
		if(!$file = @fopen($path.$name,$mode)){
			if($mode=='x')
			return 'ERROR : "'.$path.$name.'" already exists !';
			else
			return 'ERROR : "'.$path.$name.'" cannot be opened !';
		}

		// fields in databases
		$html='';
		$check = new TableInfos();
		$cols=$check->tableRows($table);
		foreach($cols as $val){
			if($val[0] != 'id'){
				// check field type
				$val=str_replace(array("'","\""), "", $val);
				$isText=stristr($val[1],'text');
				$isBlob=stristr($val[1],'blob');
				$isEnumType=stristr($val[1],'enum');
				$isSetType =stristr($val[1],'set');
				$isNum=stristr($val[1],'int') || stristr($val[1],'dec') || stristr($val[1],'numeric')
				|| stristr($val[1],'float') || stristr($val[1],'real') || stristr($val[1],'double');

				$html.="\n<h4>".$val[0]."</h4>\n";
				if($isText || $isBlob){
					// create textarea
					$html.="<textarea name='".$val[0]."' value=''></textarea>\n";

				}else if($isEnumType){
					// create select with options
					strtok($val[1],"(");
					$choice=strtok(",)");
					$html.="<select>\n";
					while($choice !== false){
						$html.="<option name='".$val[0]."' value='".$choice."'>".$choice."</option>\n";
						$choice=strtok(",)");
					}
					$html.="</select>\n";

				}else if($isSetType){
					// create checkbox buttons
					strtok($val[1],"(");
					$choice=strtok(",)");
					while($choice !== false){
						$html.="<input type='checkbox' name='".$val[0].'_'.$choice."' value='".$choice."' id='".$val[0].'_'.$choice."' /><label for='".$val[0].'_'.$choice."'>".$choice."</label><br />\n";
						$choice=strtok(",)");
					}

				}else{
					// standard input
					if($isNum){
						$html.="<input type='text' name='".$val[0]."' value='' size='8' />\n";
					}else{
						$html.="<input type='text' name='".$val[0]."' value='' size='30' />\n";
					}
				}


			}
		}

		$content= '<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" method="xml" encoding="iso-8859-1" />
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
  <head>
  <title>'.ucfirst($formType).' entry</title>
  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
	</head>
	<body>
	  <h2>'.ucfirst($formType).' entry</h2>
	  <form method="post" action="index.php?action='.$formType.ucfirst($table).'">
'.$html.'

  <p><input type="submit" value="Submit" /></p>
  </form>
	</body>
</html>
</xsl:template>
</xsl:stylesheet>
';

		// write file
		if(@fwrite($file, $content) === FALSE) {
			return 'ERROR : "'.$path.$name.'" content not written';
		}

		return 'View generated in '.$path.$name;

	} /* END of View */

}

?>
